


'''
开始，随机产生K个簇心
将点分配给最近的簇心，得到分类，计算分类的中心位置
重新分配，（循环，直到新旧簇心不发生变化）
'''


import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation

# 生成模拟数据
np.random.seed(0)
X = np.vstack((np.random.normal(-2, 1, (25, 2)), np.random.normal(2, 1, (25, 2))))
print('.................................................np.random.normal(0, 0.5, (25, 2))')
print(np.random.normal(0, 0.5, (3, 2)))
'''
第一个参数 0：表示正态分布的均值（mean）。
第二个参数 0.5：表示正态分布的标准差（standard deviation）。
第三个参数 (3, 2)：表示输出数组的形状（shape），这里是一个 3x2 的数组。
'''

# 初始化质心
centroids = np.random.normal(1, 1, (2, 2))
print('.................................................centroids')
print(centroids)

fig, ax = plt.subplots()

def update(num):
    global centroids
    ax.clear()
    
    # Step 1: Assign each data point to the closest centroid
    labels = np.argmin(np.linalg.norm(X[:, np.newaxis] - centroids, axis=2), axis=1)        # 将点分配给最近的centroid进行分类
    
    # Plot points and centroids
    ax.scatter(X[:, 0], X[:, 1], c=labels)
    ax.scatter(centroids[:, 0], centroids[:, 1], c='red', marker='X')
    
    # Step 2: Update centroid
    for i in range(2):
        centroids[i] = np.mean(X[labels == i], axis=0)

ani = animation.FuncAnimation(fig, update, frames=10, interval=1000)   # kmeans迭代的次数由frames决定
plt.show()




# ------------------------------------------------------------------------- 放法2，动态决定合适停止
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation

# 初始化数据和变量
np.random.seed(0)
X = np.vstack((np.random.normal(-2, 1, (25, 2)), np.random.normal(2, 1, (25, 2))))
centroids = np.random.normal(1, 1, (2, 2))

fig, ax = plt.subplots()

def update(num):
    global centroids

    ax.clear()

    # Step 1: Assign each data point to the closest centroid
    labels = np.argmin(np.linalg.norm(X[:, np.newaxis] - centroids, axis=2), axis=1)

    # Plot points and centroids
    ax.scatter(X[:, 0], X[:, 1], c=labels)
    ax.scatter(centroids[:, 0], centroids[:, 1], c='red', marker='X')
    
    # Step 2: Update centroid
    new_centroids = np.array([np.mean(X[labels == i], axis=0) for i in range(2)])

    # Check for convergence
    if np.all(np.abs(new_centroids - centroids) < 1e-6):
        print("Converged, stopping iteration.")
        ani.event_source.stop()

    centroids = new_centroids

ani = animation.FuncAnimation(fig, update, frames=1000, repeat=False, interval=1000)  # Set repeat to False
plt.show()